package com.java110.mall.cart.storeOrderEngine;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.java110.dto.user.UserDto;
import com.java110.intf.user.IUserV1InnerServiceSMO;
import com.java110.mall.cart.bmo.cart.impl.CartBMOImpl;
import com.java110.core.annotation.Java110Transactional;
import com.java110.core.factory.GenerateCodeFactory;
import com.java110.core.factory.Java110TransactionalFactory;
import com.java110.core.log.LoggerFactory;
import com.java110.dto.app.AppDto;
import com.java110.dto.chain.StoreOrderChainDto;
import com.java110.dto.storeOrder.StoreOrderDto;
import com.java110.dto.storeOrder.StoreOrderReturnPayDto;
import com.java110.dto.storeOrder.StoreOrderUserRoleDto;
import com.java110.dto.storeOrder.StoreOrderCartDto;
import com.java110.dto.user.UserAddressDto;
import com.java110.intf.cart.IStoreOrderAddressInnerServiceSMO;
import com.java110.intf.cart.IStoreOrderInnerServiceSMO;
import com.java110.intf.chain.IChainCoreInnerServiceSMO;
import com.java110.intf.dev.IAppV1InnerServiceSMO;
import com.java110.intf.user.IUserAddressInnerServiceSMO;
import com.java110.po.storeOrder.StoreOrderPo;
import com.java110.po.storeOrder.StoreOrderAddressPo;
import com.java110.po.storeOrder.StoreOrderCartPo;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.util.Assert;
import com.java110.utils.util.BeanConvertUtil;
import com.java110.utils.util.ListUtil;
import com.java110.utils.util.StringUtil;
import com.java110.vo.ResultVo;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @ClassName StoreOrderEngine
 * @Description TODO
 * @Author wuxw
 * @Date 2022/5/21 0:32
 * @Version 1.0
 * add by wuxw 2022/5/21
 **/
@Component
public class StoreOrderEngine {

    private final static Logger logger = LoggerFactory.getLogger(CartBMOImpl.class);

    @Autowired
    private IAppV1InnerServiceSMO appInnerServiceSMOImpl;

    @Autowired
    private StoreOrderUserEngine storeOrderUserEngine;

    @Autowired
    private StoreOrderCartEngine storeOrderCartEngine;

    @Autowired
    private StoreOrderDistribution storeOrderDistribution;

    @Autowired
    private StoreOrderComputePrice storeOrderComputePrice;

    @Autowired
    private StoreOrderCartDiscount storeOrderCartDiscount;

    @Autowired
    private IStoreOrderInnerServiceSMO storeOrderInnerServiceSMOImpl;

    @Autowired
    private IUserAddressInnerServiceSMO userAddressInnerServiceSMOImpl;

    @Autowired
    private IStoreOrderAddressInnerServiceSMO storeOrderAddressInnerServiceSMOImpl;

    @Autowired
    private IChainCoreInnerServiceSMO chainCoreInnerServiceSMOImpl;

    @Autowired
    private IUserV1InnerServiceSMO userV1InnerServiceSMOImpl;

    public static final String CHAIN_SWITCH = "CHAIN_SWITCH";
    public static final String CHAIN_SWITCH_ON = "ON";


    @Java110Transactional
    public StoreOrderReturnPayDto unifiedOrder(JSONObject param) {

        logger.debug("统一下单入参：{}", param.toJSONString());

        if (!param.containsKey("storeOrder")) {
            throw new IllegalArgumentException("不包含订单信息");
        }

        if (!param.containsKey("storeOrderCarts")) {
            throw new IllegalArgumentException("不包含订单项");
        }

        JSONObject storeOrder = param.getJSONObject("storeOrder");
        JSONArray storeOrderCarts = param.getJSONArray("storeOrderCarts");

        if (ListUtil.isNull(storeOrderCarts)) {
            throw new IllegalArgumentException("不包含订单项");
        }

        // 1.0 处理 订单
        StoreOrderPo storeOrderPo = initStoreOrderPo(param, storeOrder);

        // 2.0 查询订单用户信息
        StoreOrderUserRoleDto storeOrderUserDto = storeOrderUserEngine.queryStoreOrderUser(storeOrderPo, storeOrderCarts, param);

        //3.0 处理商品
        List<StoreOrderCartPo> storeOrderCartPos = storeOrderCartEngine.doGoods(storeOrderPo, storeOrderCarts, storeOrderUserDto, param);

        //4.0 处理 派送
        storeOrderDistribution.doDistributionMode(storeOrderPo, storeOrderCarts);

        //5.0如果商品又优惠写入优惠
        storeOrderComputePrice.dealOrderDiscountPrice(storeOrder, storeOrderPo, storeOrderCarts);

        //6.0 计算费用
        StoreOrderReturnPayDto storeOrderReturnPayDto = storeOrderComputePrice.computeStoreOrderFee(storeOrderPo, storeOrderCarts, storeOrderCartPos, storeOrderUserDto);

        //7.0 添加订单
        int flag = storeOrderInnerServiceSMOImpl.saveStoreOrder(storeOrderPo);

        if (flag < 1) {
            throw new IllegalArgumentException("保存失败");
        }

        //8.0 保存收货人信息
        saveOrderAddress(storeOrderPo, param);


        //9.0 会员优惠
        storeOrderCartDiscount.sendVipDiscount(param, storeOrderCartPos, storeOrderPo);

        //10.0 校验调用链
        validateChain(storeOrderPo, storeOrderCartPos);


        return storeOrderReturnPayDto;

    }

    /**
     * 校验调用链
     *
     * @param storeOrderPo
     * @param storeOrderCartPos
     */
    private void validateChain(StoreOrderPo storeOrderPo, List<StoreOrderCartPo> storeOrderCartPos) {

        String chainSwitch = MappingCache.getValue(CHAIN_SWITCH);
        if (!CHAIN_SWITCH_ON.equals(chainSwitch)) {
            return;
        }

        StoreOrderChainDto storeOrderChainDto = new StoreOrderChainDto();
        storeOrderChainDto.setStoreOrderDto(BeanConvertUtil.covertBean(storeOrderPo, StoreOrderDto.class));
        storeOrderChainDto.setStoreOrderCartDtos(BeanConvertUtil.covertBeanList(storeOrderCartPos, StoreOrderCartDto.class));

        ResultVo resultVo = null;
        try {
            resultVo = chainCoreInnerServiceSMOImpl.validateChainOrder(storeOrderChainDto);
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage());
        }

        if (resultVo.getCode() != ResultVo.CODE_OK) {
            throw new IllegalArgumentException(resultVo.getMsg());
        }
    }


    private StoreOrderPo initStoreOrderPo(JSONObject param, JSONObject storeOrder) {
        AppDto appDto = new AppDto();
        appDto.setAppId(param.getString("appId"));
        List<AppDto> appDtos = appInnerServiceSMOImpl.queryApps(appDto);

        Assert.listOnlyOne(appDtos, "应用不存在");

        StoreOrderPo storeOrderPo = BeanConvertUtil.covertBean(storeOrder, StoreOrderPo.class);
        storeOrderPo.setOrderId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_orderId));
        storeOrderPo.setPayPrice(storeOrder.getString("payPrice"));
        storeOrderPo.setAppId(appDtos.get(0).getAppId());
        storeOrderPo.setAppName(appDtos.get(0).getName());
        storeOrderPo.setTotalPrice("0");
        storeOrderPo.setFreightPrice("0");
        storeOrderPo.setState(StoreOrderDto.STATE_WAIT_PAY);
        storeOrderPo.setShopId(param.getString("shopId"));
        if (AppDto.MALL_APP_ID.equals(appDtos.get(0).getAppId())) {
            storeOrderPo.setState(StoreOrderDto.STATE_FINISH_PAY);
        }
        storeOrderPo.setOId(StringUtil.isEmpty(Java110TransactionalFactory.getOId()) ? "-1" : Java110TransactionalFactory.getOId());
        if (StringUtil.isEmpty(storeOrderPo.getPersonId())) {
            storeOrderPo.setPersonId("-1");
            storeOrderPo.setPersonName("未知");
            return storeOrderPo;
        }

        UserDto userDto = new UserDto();
        userDto.setUserId(storeOrderPo.getPersonId());
        List<UserDto> userDtos = userV1InnerServiceSMOImpl.queryUsers(userDto);
        if(ListUtil.isNull(userDtos)){
            storeOrderPo.setPersonName("未知");
            return storeOrderPo;
        }

        storeOrderPo.setPersonName(userDtos.get(0).getName());
        return storeOrderPo;
    }


    private void saveOrderAddress(StoreOrderPo storeOrderPo, JSONObject param) {

        if (!param.containsKey("addressId")) {
            return;
        }

        UserAddressDto userAddressDto = new UserAddressDto();
        userAddressDto.setAddressId(param.getString("addressId"));
        userAddressDto.setUserId(storeOrderPo.getPersonId());
        List<UserAddressDto> userAddressDtos = userAddressInnerServiceSMOImpl.queryUserAddresss(userAddressDto);

        Assert.listOnlyOne(userAddressDtos, "未找到收货人信息");

        userAddressDto = userAddressDtos.get(0);

        StoreOrderAddressPo storeOrderAddressPo = new StoreOrderAddressPo();
        storeOrderAddressPo.setAddress(userAddressDto.getAddress());
        storeOrderAddressPo.setAddressId(userAddressDto.getAddressId());
        storeOrderAddressPo.setAreaCode(userAddressDto.getAreaCode());
        storeOrderAddressPo.setOaId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_oaId));
        storeOrderAddressPo.setOrderId(storeOrderPo.getOrderId());
        storeOrderAddressPo.setTel(userAddressDto.getTel());
        storeOrderAddressPo.setUsername(userAddressDto.getUsername());

        int flag = storeOrderAddressInnerServiceSMOImpl.saveStoreOrderAddress(storeOrderAddressPo);

        if (flag < 1) {
            throw new IllegalArgumentException("保存收货人信息失败");
        }

    }
}
